//
// (C) Copyright 2009 Irantha Suwandarathna (irantha@gmail.com)
// All rights reserved.
//
/* Copyright (c) 2001-2008, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use _in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions _in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer _in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


using System;
using System.Text;
using System.Collections.Generic;
using System.Reflection;
using EffiProzDB.DataTypes;
using EffiProzDB.Lib;


namespace EffiProzDB
{

    // fredt@users - 1.7.2 - structural modifications to allow inheritance
    // boucherB@users 20020305 - completed inheritance work, including const access
    // boucherB@users 20020305 - javadoc updates/corrections
    // boucherB@users 20020305 - SYSTEM_VIEWS brought _in line with SQL 200n
    // boucherb@users 20050514 - further SQL 200n metdata support

    /**
     * Base class for system tables. Includes a factory method which returns the
     * most complete implementation available _in the jar. This base implementation
     * knows the names of all system tables but returns null for any system table.
     * <p>
     * This class has been developed from scratch to replace the previous
     * DatabaseInformation implementations. <p>
     *
     * @author boucherb@users
     * @version 1.8.0
     * @since 1.7.2
     */
    public class DatabaseInformation
    {

        // ids for system table names strictly _in order of sysTableNames[]
        protected const int _SYSTEM_BESTROWIDENTIFIER = 0;
        protected const int _SYSTEM_CATALOGS = 1;
        protected const int _SYSTEM_COLUMNPRIVILEGES = 2;
        protected const int _SYSTEM_COLUMNS = 3;
        protected const int _SYSTEM_CROSSREFERENCE = 4;
        protected const int _SYSTEM_INDEXINFO = 5;
        protected const int _SYSTEM_PRIMARYKEYS = 6;
        protected const int _SYSTEM_PROCEDURECOLUMNS = 7;
        protected const int _SYSTEM_PROCEDURES = 8;
        protected const int _SYSTEM_SCHEMAS = 9;
        protected const int _SYSTEM_SUPERTABLES = 10;
        protected const int _SYSTEM_SUPERTYPES = 11;
        protected const int _SYSTEM_TABLEPRIVILEGES = 12;
        protected const int _SYSTEM_TABLES = 13;
        protected const int _SYSTEM_TABLETYPES = 14;
        protected const int _SYSTEM_TYPEINFO = 15;
        protected const int _SYSTEM_UDTATTRIBUTES = 16;
        protected const int _SYSTEM_UDTS = 17;
        protected const int _SYSTEM_USERS = 18;
        protected const int _SYSTEM_VERSIONCOLUMNS = 19;

        // HSQLDB-specific
        protected const int _SYSTEM_ALIASES = 20;
        protected const int _SYSTEM_BYTECODE = 21;
        protected const int _SYSTEM_CACHEINFO = 22;
        protected const int _SYSTEM_CLASSPRIVILEGES = 23;
        protected const int _SYSTEM_SESSIONINFO = 24;
        protected const int _SYSTEM_PROPERTIES = 25;
        protected const int _SYSTEM_SESSIONS = 26;
        protected const int _SYSTEM_TRIGGERCOLUMNS = 27;
        protected const int _SYSTEM_TRIGGERS = 28;
        protected const int _SYSTEM_ALLTYPEINFO = 29;

        // boucherb@users 20030305 - brought _in line with SQL 200n
        protected const int _SYSTEM_VIEWS = 30;

        // boucherb@users 20030403 - isolated and improved text table reporting
        protected const int _SYSTEM_TEXTTABLES = 31;

        // boucherb@users 20040107 - metadata support for sequences
        protected const int _SYSTEM_SEQUENCES = 32;
        protected const int _SYSTEM_USAGE_PRIVILEGES = 33;

        // boucherb@users 20040107 - metadata support for constraints
        protected const int _SYSTEM_CHECK_CONSTRAINTS = 34;
        protected const int _SYSTEM_TABLE_CONSTRAINTS = 35;

        // boucherb@users 20040107 - metadata support for view usage breakdown- SQL 200n
        protected const int _SYSTEM_CHECK_COLUMN_USAGE = 36;
        protected const int _SYSTEM_CHECK_ROUTINE_USAGE = 37;
        protected const int _SYSTEM_CHECK_TABLE_USAGE = 38;
        protected const int _SYSTEM_VIEW_COLUMN_USAGE = 39;
        protected const int _SYSTEM_VIEW_TABLE_USAGE = 40;
        protected const int _SYSTEM_VIEW_ROUTINE_USAGE = 41;

        // boucherb@users 20050514 - further SQL 200n metdata support
        protected const int _SYSTEM_AUTHORIZATIONS = 42;
        protected const int _SYSTEM_COLLATIONS = 43;
        protected const int _SYSTEM_ROLE_AUTHORIZATION_DESCRIPTORS = 44;
        protected const int _SYSTEM_SCHEMATA = 45;

        /** system table names strictly _in order of their ids */
        protected static readonly String[] sysTableNames = {
        "SYSTEM_BESTROWIDENTIFIER",                 //
        "SYSTEM_CATALOGS",                          //
        "SYSTEM_COLUMNPRIVILEGES",                  //
        "SYSTEM_COLUMNS",                           //
        "SYSTEM_CROSSREFERENCE",                    //
        "SYSTEM_INDEXINFO",                         //
        "SYSTEM_PRIMARYKEYS",                       //
        "SYSTEM_PROCEDURECOLUMNS",                  //
        "SYSTEM_PROCEDURES",                        //
        "SYSTEM_SCHEMAS",                           //
        "SYSTEM_SUPERTABLES",                       //
        "SYSTEM_SUPERTYPES",                        //
        "SYSTEM_TABLEPRIVILEGES",                   //
        "SYSTEM_TABLES",                            //
        "SYSTEM_TABLETYPES",                        //
        "SYSTEM_TYPEINFO",                          //
        "SYSTEM_UDTATTRIBUTES",                     //
        "SYSTEM_UDTS",                              //
        "SYSTEM_USERS",                             //
        "SYSTEM_VERSIONCOLUMNS",                    //

        // HSQLDB-specific
        "SYSTEM_ALIASES",                           //
        "SYSTEM_BYTECODE",                          //
        "SYSTEM_CACHEINFO",                         //
        "SYSTEM_CLASSPRIVILEGES",                   //
        "SYSTEM_SESSIONINFO",                       //
        "SYSTEM_PROPERTIES",                        //
        "SYSTEM_SESSIONS",                          //
        "SYSTEM_TRIGGERCOLUMNS",                    //
        "SYSTEM_TRIGGERS",                          //
        "SYSTEM_ALLTYPEINFO",                       //

        // boucherb@users 20030305 - brought _in line with SQL 200n
        "SYSTEM_VIEWS",

        // boucherb@users 20030403 - isolated and improved text table reporting
        "SYSTEM_TEXTTABLES",

        // boucherb@users 20040107 - metadata support for sequences - SQL 200n
        "SYSTEM_SEQUENCES",                         //
        "SYSTEM_USAGE_PRIVILEGES",

        // boucherb@users 20040107 - metadata support for constraints - SQL 200n
        "SYSTEM_CHECK_CONSTRAINTS",                 //
        "SYSTEM_TABLE_CONSTRAINTS",                 //

        // boucherb@users 20040107 - metadata support for usage - SQL 200n
        "SYSTEM_CHECK_COLUMN_USAGE",                //
        "SYSTEM_CHECK_ROUTINE_USAGE",               //
        "SYSTEM_CHECK_TABLE_USAGE",                 //
        "SYSTEM_VIEW_COLUMN_USAGE",                 //
        "SYSTEM_VIEW_TABLE_USAGE",                  //
        "SYSTEM_VIEW_ROUTINE_USAGE",                //

        // boucherb@users 20050514 - further SQL 200n metadata support
        "SYSTEM_AUTHORIZATIONS",                    //
        "SYSTEM_COLLATIONS",                        //
        "SYSTEM_ROLE_AUTHORIZATION_DESCRIPTORS",    //
        "SYSTEM_SCHEMATA"                           //

        // Future use
//        "SYSTEM_ASSERTIONS",
//        "SYSTEM_ATTRIBUTES",
//        "SYSTEM_AUTHORIZATIONS",                 // boucherb@users 20050514 - implemented
//        "SYSTEM_CHARACTER_ENCODING_FORMS",
//        "SYSTEM_CHARACTER_REPERTOIRES",
//        "SYSTEM_CHARACTER_SETS",
//        "SYSTEM_CHECK_COLUMN_USAGE",             // boucherb@users 20040107 - implemented
//        "SYSTEM_CHECK_ROUTINE_USAGE",            // boucherb@users 20040107 - implemented
//        "SYSTEM_CHECK_CONSTRAINTS",              // boucherb@users 20040107 - implemented
//        "SYSTEM_CHECK_TABLE_USAGE",              // boucherb@users 20040107 - implemented
//        "SYSTEM_COLLATION_CHARACTER_SET_APPLICABILITY",
//        "SYSTEM_COLLATIONS",                     // boucherb@users 20050514 - implemented
//        "SYSTEM_COLUMN_COLUMN_USAGE",
//        "SYSTEM_COLUMN_OPTIONS",
//        "SYSTEM_COLUMN_PRIVILEGES",
//        "SYSTEM_COLUMNS",
//        "SYSTEM_DATA_TYPE_DESCRIPTOR",
//        "SYSTEM_DIRECT_SUPERTABLES",
//        "SYSTEM_DIRECT_SUPERTYPES",
//        "SYSTEM_DOMAIN_CONSTRAINTS",
//        "SYSTEM_DOMAINS",
//        "SYSTEM_ELEMENT_TYPES",
//        "SYSTEM_FIELDS",
//        "SYSTEM_FOREIGN_DATA_WRAPPER_OPTIONS",
//        "SYSTEM_FOREIGN_DATA_WRAPPERS",
//        "SYSTEM_FOREIGN_SERVER_OPTIONS",
//        "SYSTEM_FOREIGN_SERVERS",
//        "SYSTEM_FOREIGN_TABLE_OPTIONS",
//        "SYSTEM_FOREIGN_TABLES",
//        "SYSTEM_JAR_JAR_USAGE",
//        "SYSTEM_JARS",
//        "SYSTEM_KEY_COLUMN_USAGE",
//        "SYSTEM_METHOD_SPECIFICATION_PARAMETERS",
//        "SYSTEM_METHOD_SPECIFICATIONS",
//        "SYSTEM_MODULE_COLUMN_USAGE",
//        "SYSTEM_MODULE_PRIVILEGES",
//        "SYSTEM_MODULE_TABLE_USAGE",
//        "SYSTEM_MODULES",
//        "SYSTEM_PARAMETERS",
//        "SYSTEM_REFERENCED_TYPES",
//        "SYSTEM_REFERENTIAL_CONSTRAINTS",
//        "SYSTEM_ROLE_AUTHORIZATION_DESCRIPTORS", // boucherb@users 20050514 - implemented
//        "SYSTEM_ROLES",
//        "SYSTEM_ROUTINE_COLUMN_USAGE",
//        "SYSTEM_ROUTINE_JAR_USAGE",
//        "SYSTEM_ROUTINE_MAPPING_OPTIONS",
//        "SYSTEM_ROUTINE_MAPPINGS",
//        "SYSTEM_ROUTINE_PRIVILEGES",
//        "SYSTEM_ROUTINE_ROUTINE_USAGE",
//        "SYSTEM_ROUTINE_SEQUENCE_USAGE",
//        "SYSTEM_ROUTINE_TABLE_USAGE",
//        "SYSTEM_ROUTINES",
//        "SYSTEM_SCHEMATA",                       // boucherb@users 20050514 - implemented
//        "SYSTEM_SEQUENCES",                      // boucherb@users 20040107 - implemented
//        "SYSTEM_SQL_FEATURES",
//        "SYSTEM_SQL_IMPLEMENTATION_INFO",
//        "SYSTEM_SQL_LANGUAGES",
//        "SYSTEM_SQL_SIZING",
//        "SYSTEM_SQL_SIZING_PROFILES",
//        "SYSTEM_TABLE_CONSTRAINTS",              // boucherb@users 20040107 - implemented
//        "SYSTEM_TABLE_METHOD_PRIVILEGES",
//        "SYSTEM_TABLE_PRIVILEGES",
//        "SYSTEM_TABLES",
//        "SYSTEM_TRANSFORMS",
//        "SYSTEM_TRANSLATIONS",
//        "SYSTEM_TRIGGER_COLUMN_USAGE",
//        "SYSTEM_TRIGGER_ROUTINE_USAGE",
//        "SYSTEM_TRIGGER_SEQUENCE_USAGE",
//        "SYSTEM_TRIGGER_TABLE_USAGE",
//        "SYSTEM_TRIGGERED_UPDATE_COLUMNS",
//        "SYSTEM_TRIGGERS",
//        "SYSTEM_TYPE_JAR_USAGE",
//        "SYSTEM_USAGE_PRIVILEGES",               // boucherb@users 20040107 - implemented
//        "SYSTEM_USER_DEFINED_TYPE_PRIVILEGES",
//        "SYSTEM_USER_DEFINED_TYPES",
//        "SYSTEM_USER_MAPPING_OPTIONS",
//        "SYSTEM_USER_MAPPINGS",
//        "SYSTEM_USERS",
//        "SYSTEM_VIEW_COLUMN_USAGE",              // boucherb@users 20040107 - implemented
//        "SYSTEM_VIEW_ROUTINE_USAGE",             // boucherb@users 20040107 - implemented
//        "SYSTEM_VIEW_TABLE_USAGE",               // boucherb@users 20040107 - implemented
//        "SYSTEM_VIEWS", // boucherb@users 20030305 - implemented
    };

        /** Map: table name => table id */
        protected static Dictionary<string, int> sysTableNamesMap;

        static DatabaseInformation()
        {
            sysTableNamesMap = new Dictionary<string, int>(47);

            for (int i = 0; i < sysTableNames.Length; i++)
            {
                sysTableNamesMap.Add(sysTableNames[i], i);
            }
        }

        public static int getSysTableID(string token)
        {
            int tid = -1;
            sysTableNamesMap.TryGetValue(token, out tid);
            return tid;
        }

        /** Database for which to produce tables */
        protected static Database database;

        /**
         * Simple object-wide flag indicating that all of this object's cached
         * data is dirty.
         */
        protected bool isDirty = true;

        /**
         * state flag -- if true, contentful tables are to be produced, else
         * empty (surrogate) tables are to be produced.  This allows faster
         * database startup where user views reference system tables and faster
         * system table structural reflection for table metadata.
         */
        protected bool withContent = false;

        /**
         * Factory method retuns the fullest system table producer
         * implementation available.  This instantiates implementations beginning
         * with the most complete, finally choosing an empty table producer
         * implemenation (this class) if no better instance can be constructed.
         * @param db The Database object for which to produce system tables
         * @return the fullest system table producer
         *      implementation available
         * @  never - required by constructor
         */
        public static DatabaseInformation newDatabaseInformation(Database db)
        {

            Type clazz = null;

            try
            {
                clazz = Type.GetType("EffiProzDB.DatabaseInformationFull");
            }
            catch (Exception)
            {
                try
                {
                    clazz = Type.GetType("EffiProzDB.DatabaseInformationMain");
                }
                catch (Exception) { }
            }

            try
            {
                Type[] ctorParmTypes = new Type[] { typeof(Database) };
                Object[] ctorParms = new Object[] { db };
                ConstructorInfo ctor = clazz.GetConstructor(ctorParmTypes);

                return (DatabaseInformation)ctor.Invoke(ctorParms);
            }
            catch (Exception ) { }

            return new DatabaseInformation(db);
        }

        /**
         * Constructs a new DatabaseInformation instance which knows the names of
         * all system tables (isSystemTable()) but simpy returns null for all
         * getSystemTable() requests. <p>
         *
         * @param db The Database object for which to produce system tables
         * @  never (required for descendents)
         */
        public DatabaseInformation(Database db)
        {
            database = db;
        }

        /**
         * Tests if the specified name is that of a system table. <p>
         *
         * @param name the name to test
         * @return true if the specified name is that of a system table
         */
        public static bool isSystemTable(string name)
        {
            return sysTableNamesMap.ContainsKey(name);
        }

        /**
         * Retrieves a table with the specified name whose content may depend on
         * the execution context indicated by the session argument as well as the
         * current value of <code>withContent</code>. <p>
         *
         * @param session the context _in which to produce the table
         * @param name the name of the table to produce
         * @  if a database access error occurs
         * @return a table corresponding to the name and session arguments, or
         *      <code>null</code> if there is no such table to be produced
         */
        public virtual Table getSystemTable(Session session, string name)
        {
            return null;
        }

        /**
         * Controls caching of all tables produced by this object. <p>
         *
         * Subclasses are free to ignore this, since they may choose an
         * implementation that does not dynamically generate and/or cache
         * table content on an as-needed basis. <p>
         *
         * If not ignored, this call indicates to this object that all cached
         * table data may be dirty, requiring a complete cache clear at some
         * point.<p>
         *
         * Subclasses are free to delay cache clear until next getSystemTable().
         * However, subclasses may have to be aware of additional methods with
         * semantics similar to getSystemTable() and act accordingly (e.g.
         * clearing earlier than next invocation of getSystemTable()).
         */
        public void setDirty()
        {
            isDirty = true;
        }

        /**
         * Switches this table producer between producing empty (surrogate)
         * or contentful tables. <p>
         *
         * @param withContent if true, then produce contentful tables, else
         *        produce emtpy (surrogate) tables
         */
        public void setWithContent(bool withContent)
        {
            this.withContent = withContent;
        }
    }
}
